﻿using System;
using UnityEngine;
using EchoFramework;
using System.Collections.Generic;

/// <summary>
/// 地图点Item
/// </summary>
public class MapRoadItem : ObjectBase
{
    private PrefabBinder prefabBinder;
    private Transform gridTrans;
    private SpriteRenderer pointSr;
    private Canvas canvas;
    private EchoText pointPropTxt;
    private EchoText conditionLeftTxt;
    private EchoText conditionRightTxt;
    private EchoText conditionUpTxt;
    private EchoText conditionDownTxt;
    private Transform roadTrans;
    private Transform leftTrans;
    private Transform rightTrans;
    private Transform upTrans;
    private Transform downTrans;
    private Transform arrowTrans;
    private Transform leftNoArrowTrans;
    private Transform rightNoArrowTrans;
    private Transform upNoArrowTrans;
    private Transform downNoArrowTrans;
    private Transform leftArrowTrans;
    private Transform rightArrowTrans;
    private Transform upArrowTrans;
    private Transform downArrowTrans;

    /// <summary>
    /// 绿色
    /// </summary>
    [SerializeField]
    private Material greenColorMat;

    /// <summary>
    /// 黄色
    /// </summary>
    [SerializeField]
    private Material yellowColorMat;

    /// <summary>
    /// 红色
    /// </summary>
    [SerializeField]
    private Material redColorMat;
    
    /// <summary>
    /// 坐标点
    /// </summary>
    public Coordinate Coor { get; private set; }

    /// <summary>
    /// 位点枚举
    /// </summary>
    public PosTypeEnum PosTypeEnum { get; private set; } = PosTypeEnum.Null;
    
    /// <summary>
    /// 自身地图点位配置
    /// </summary>
    public MapPosCfg mapPosCfg;

    /// <summary>
    /// 出口配置列表
    /// </summary>
    private List<MapPosCfg> outMapPosCfgList = new List<MapPosCfg>();

    /// <summary>
    /// 入口配置列表
    /// </summary>
    private List<MapPosCfg> inMapPosCfgList = new List<MapPosCfg>();

    private void Awake()
    {
        prefabBinder = GetComponent<PrefabBinder>();
        gridTrans = prefabBinder.Find("GridTrans").GetComponent<Transform>();
        pointSr = prefabBinder.Find("PointSr").GetComponent<SpriteRenderer>();
        canvas = prefabBinder.Find("Canvas").GetComponent<Canvas>();
        pointPropTxt = prefabBinder.Find("PointPropTxt").GetComponent<EchoText>();
        conditionLeftTxt = prefabBinder.Find("ConditionLeftTxt").GetComponent<EchoText>();
        conditionRightTxt = prefabBinder.Find("ConditionRightTxt").GetComponent<EchoText>();
        conditionUpTxt = prefabBinder.Find("ConditionUpTxt").GetComponent<EchoText>();
        conditionDownTxt = prefabBinder.Find("ConditionDownTxt").GetComponent<EchoText>();
        roadTrans = prefabBinder.Find("RoadTrans").GetComponent<Transform>();
        leftTrans = prefabBinder.Find("LeftTrans").GetComponent<Transform>();
        rightTrans = prefabBinder.Find("RightTrans").GetComponent<Transform>();
        upTrans = prefabBinder.Find("UpTrans").GetComponent<Transform>();
        downTrans = prefabBinder.Find("DownTrans").GetComponent<Transform>();
        arrowTrans = prefabBinder.Find("ArrowTrans").GetComponent<Transform>();
        leftNoArrowTrans = prefabBinder.Find("LeftNoArrowTrans").GetComponent<Transform>();
        rightNoArrowTrans = prefabBinder.Find("RightNoArrowTrans").GetComponent<Transform>();
        upNoArrowTrans = prefabBinder.Find("UpNoArrowTrans").GetComponent<Transform>();
        downNoArrowTrans = prefabBinder.Find("DownNoArrowTrans").GetComponent<Transform>();
        leftArrowTrans = prefabBinder.Find("LeftArrowTrans").GetComponent<Transform>();
        rightArrowTrans = prefabBinder.Find("RightArrowTrans").GetComponent<Transform>();
        upArrowTrans = prefabBinder.Find("UpArrowTrans").GetComponent<Transform>();
        downArrowTrans = prefabBinder.Find("DownArrowTrans").GetComponent<Transform>();
    }

    /// <summary>
    /// 设置自身配置数据
    /// </summary>
    /// <param name="cfg">自身配置</param>
    public void SetSelfData(MapPosCfg cfg)
    {
        mapPosCfg = cfg;
        PosTypeEnum = mapPosCfg.PosTypeEnum;
        outMapPosCfgList = mapPosCfg.GetTargetIDCfgList();
        Coor = mapPosCfg.PosCoordinate;
        transform.localPosition = new Vector3(Coor.X, Coor.Y);
        RefreshArrow();
        roadTrans.gameObject.SetActive(PosTypeEnum == PosTypeEnum.MidPoint);
        gridTrans.gameObject.SetActive(PosTypeEnum != PosTypeEnum.MidPoint);
        canvas.gameObject.SetActive(PosTypeEnum != PosTypeEnum.MidPoint);
        RefreshMidRoad();
        ShowMethodStr();
        ShowConditionStr();
        switch (PosTypeEnum)
        {
            case PosTypeEnum.Start:
                pointSr.material = yellowColorMat;
                break;
            case PosTypeEnum.PosPoint:
                pointSr.material = greenColorMat;
                break;
            case PosTypeEnum.End:
                pointSr.material = redColorMat;
                pointPropTxt.text = "[End]";
                break;
        }
    }

    /// <summary>
    /// 设置空道路
    /// </summary>
    /// <param name="coor">坐标</param>
    /// <param name="isHorizontal">是否为水平</param>
    public void SetNullData(Coordinate coor, bool isHorizontal)
    {
        Coor = coor;
        transform.localPosition = new Vector3(Coor.X, Coor.Y);
        PosTypeEnum = PosTypeEnum.Null;
        RefreshArrow();
        gridTrans.gameObject.SetActive(false);
        canvas.gameObject.SetActive(false);
        roadTrans.gameObject.SetActive(true);
        leftTrans.gameObject.SetActive(isHorizontal);
        rightTrans.gameObject.SetActive(isHorizontal);
        upTrans.gameObject.SetActive(!isHorizontal);
        downTrans.gameObject.SetActive(!isHorizontal);
    }

    /// <summary>
    /// 添加入口的配置表
    /// </summary>
    /// <param name="mapPosCfg">入口配置表</param>
    public void AddInMapPosCfg(MapPosCfg mapPosCfg)
    {
        inMapPosCfgList.Add(mapPosCfg);
        RefreshArrow();
        RefreshMidRoad();
    }

    /// <summary>
    /// 添加出口的配置表 只有PosTypeEnum == Null，才走这个函数
    /// </summary>
    /// <param name="mapPosCfg">出口配置表</param>
    public void AddOutMapPosCfg(MapPosCfg mapPosCfg)
    {
        outMapPosCfgList.Add(mapPosCfg);
        RefreshArrow();
    }

    /// <summary>
    /// 中间特殊点位，刷新路径
    /// </summary>
    private void RefreshMidRoad()
    {
        if (PosTypeEnum != PosTypeEnum.MidPoint)
            return;

        leftTrans.gameObject.SetActive(false);
        rightTrans.gameObject.SetActive(false);
        upTrans.gameObject.SetActive(false);
        downTrans.gameObject.SetActive(false);
        //入口
        foreach (MapPosCfg inMapPosCfg in inMapPosCfgList)
        {
            DirectionEnum dir = GetTargetDir(inMapPosCfg.PosCoordinate);
            switch (dir)
            {
                case DirectionEnum.Left:
                    leftTrans.gameObject.SetActive(true);
                    break;
                case DirectionEnum.Right:
                    rightTrans.gameObject.SetActive(true);
                    break;
                case DirectionEnum.Up:
                    upTrans.gameObject.SetActive(true);
                    break;
                case DirectionEnum.Down:
                    downTrans.gameObject.SetActive(true);
                    break;
            }
        }

        //出口箭头
        foreach (MapPosCfg outMapPosCfg in outMapPosCfgList)
        {
            DirectionEnum dir = GetTargetDir(outMapPosCfg.PosCoordinate);
            switch (dir)
            {
                case DirectionEnum.Left:
                    leftTrans.gameObject.SetActive(true);
                    break;
                case DirectionEnum.Right:
                    rightTrans.gameObject.SetActive(true);
                    break;
                case DirectionEnum.Up:
                    upTrans.gameObject.SetActive(true);
                    break;
                case DirectionEnum.Down:
                    downTrans.gameObject.SetActive(true);
                    break;
            }
        }
    }

    /// <summary>
    /// 刷新箭头
    /// </summary>
    private void RefreshArrow()
    {
        //隐藏所有的箭头
        leftNoArrowTrans.gameObject.SetActive(false);
        rightNoArrowTrans.gameObject.SetActive(false);
        upNoArrowTrans.gameObject.SetActive(false);
        downNoArrowTrans.gameObject.SetActive(false);
        leftArrowTrans.gameObject.SetActive(false);
        rightArrowTrans.gameObject.SetActive(false);
        upArrowTrans.gameObject.SetActive(false);
        downArrowTrans.gameObject.SetActive(false);

        //记录处理过的方向
        List<DirectionEnum> recordDirList = new List<DirectionEnum>();
        bool isRoadPath = PosTypeEnum == PosTypeEnum.Null || PosTypeEnum == PosTypeEnum.MidPoint;
        //入口箭头
        foreach (MapPosCfg inMapPosCfg in inMapPosCfgList)
        {
            DirectionEnum dir = GetTargetDir(inMapPosCfg.PosCoordinate);
            switch (dir)
            {
                case DirectionEnum.Left:
                    if (isRoadPath)
                    {
                        leftNoArrowTrans.gameObject.SetActive(true);
                    }
                    else
                    {
                        leftArrowTrans.gameObject.SetActive(true);
                    }

                    break;
                case DirectionEnum.Right:
                    if (isRoadPath)
                    {
                        rightNoArrowTrans.gameObject.SetActive(true);
                    }
                    else
                    {
                        rightArrowTrans.gameObject.SetActive(true);
                    }

                    break;
                case DirectionEnum.Up:
                    if (isRoadPath)
                    {
                        upNoArrowTrans.gameObject.SetActive(true);
                    }
                    else
                    {
                        upArrowTrans.gameObject.SetActive(true);
                    }

                    break;
                case DirectionEnum.Down:
                    if (isRoadPath)
                    {
                        downNoArrowTrans.gameObject.SetActive(true);
                    }

                    else
                    {
                        downArrowTrans.gameObject.SetActive(true);
                    }

                    break;
            }

            recordDirList.Add(dir);
        }

        //出口箭头
        foreach (MapPosCfg outMapPosCfg in outMapPosCfgList)
        {
            DirectionEnum dir = GetTargetDir(outMapPosCfg.PosCoordinate);
            if (recordDirList.Contains(dir))
                continue;
            switch (dir)
            {
                case DirectionEnum.Left:
                    leftNoArrowTrans.gameObject.SetActive(true);
                    break;
                case DirectionEnum.Right:
                    rightNoArrowTrans.gameObject.SetActive(true);
                    break;
                case DirectionEnum.Up:
                    upNoArrowTrans.gameObject.SetActive(true);
                    break;
                case DirectionEnum.Down:
                    downNoArrowTrans.gameObject.SetActive(true);
                    break;
            }
        }
    }

    /// <summary>
    /// 显示计算方式文本
    /// </summary>
    private void ShowMethodStr()
    {
        if (PosTypeEnum != PosTypeEnum.Start && PosTypeEnum != PosTypeEnum.PosPoint)
        {
            pointPropTxt.text = string.Empty;
            return;
        }

        if (string.IsNullOrEmpty(mapPosCfg.Method))
        {
            pointPropTxt.text = string.Empty;
            return;
        }
        
        string[] methodStrArr = mapPosCfg.Method.Split(',');
        int num = Convert.ToInt32(methodStrArr[1]);
        string showStr = string.Empty;
        switch (methodStrArr[0])
        {
            case "init":
                showStr = $"[{num}]";
                break;
            case "add":
                showStr = $"+{num}";
                break;
            case "reduce":
                showStr = $"-{num}";
                break;
            case "multi":
                showStr = $"x{num}";
                break;
            case "div":
                showStr = $"/{num}";
                break;
            default:
                showStr = string.Empty;
                break;
        }

        pointPropTxt.text = showStr;
    }

    /// <summary>
    /// 显示出口条件文本
    /// </summary>
    private void ShowConditionStr()
    {
        conditionLeftTxt.text = string.Empty;
        conditionRightTxt.text = string.Empty;
        conditionUpTxt.text = string.Empty;
        conditionDownTxt.text = string.Empty;
        
        if (PosTypeEnum != PosTypeEnum.Start && PosTypeEnum != PosTypeEnum.PosPoint)
        {
            return;
        }

        if (string.IsNullOrEmpty(mapPosCfg.Condition))
        {
            return;
        }

        string[] conditionArr = mapPosCfg.Condition.Split('|');
        if (conditionArr == null || conditionArr.Length <= 0)
            return;
        List<MapPosCfg> targetList = mapPosCfg.GetTargetIDCfgList();
        for (int i = 0; i < conditionArr.Length; i++)
        {
            string[] condArr = conditionArr[i].Split(',');
            int num = Convert.ToInt32(condArr[1]);
            string showStr = string.Empty;
            switch (condArr[0])
            {
                case "less":
                    showStr = $"<{num}";
                    break;
                case "bigger":
                    showStr = $">{num}";
                    break;
                case "equal":
                    showStr = $"={num}";
                    break;
                default:
                    showStr = string.Empty;
                    break;
            }
            
            MapPosCfg tempCfg = targetList[i];
            DirectionEnum dir = GetTargetDir(tempCfg.PosCoordinate);
            switch (dir)
            {
                case DirectionEnum.Left:
                    conditionLeftTxt.text = showStr;
                    break;
                case DirectionEnum.Right:
                    conditionRightTxt.text = showStr;
                    break;
                case DirectionEnum.Up:
                    conditionUpTxt.text = showStr;
                    break;
                case DirectionEnum.Down:
                    conditionDownTxt.text = showStr;
                    break;
            }
        }
    }
    
    /// <summary>
    /// 返回目标坐标相对于自己的方向
    /// </summary>
    /// <param name="coor">坐标点</param>
    private DirectionEnum GetTargetDir(Coordinate coor)
    {
        Coordinate selfCoor = Coor;
        int xOffset = selfCoor.X - coor.X;
        if (xOffset < 0)
        {
            return DirectionEnum.Right;
        }
        else if (xOffset > 0)
        {
            return DirectionEnum.Left;
        }

        int yOffset = selfCoor.Y - coor.Y;
        if (yOffset < 0)
        {
            return DirectionEnum.Up;
        }
        else if (yOffset > 0)
        {
            return DirectionEnum.Down;
        }

        return DirectionEnum.Null;
    }

    /// <summary>
    /// 返回目标坐标Cfg
    /// </summary>
    /// <param name="targetDir">传入前进的方向</param>
    /// <returns></returns>
    public MapPosCfg GetTargetMapPosCfg(DirectionEnum targetDir)
    {
        foreach (MapPosCfg tempCfg in outMapPosCfgList)
        {
            DirectionEnum tempDir = GetTargetDir(tempCfg.PosCoordinate);
            if (tempDir == targetDir)
                return tempCfg;
        }

        return null;
    }
}